﻿using CommonDevelop.Scene;
using CommonDevelop.SSO;
using CommonEngine;
using CommonFP;
using System;

namespace CommonDevelop.Operator
{
    public class OperatorProvider
    {
        private static readonly object @lock = new object();
        private static OperatorProvider _Provider;
        private IOperatorGetData _OperatorGetData { get; set; }
        private IOperator _Operator { get; set; }
        private SSOAdapter _Adapter { get; set; }

        public const string CURRENT_KEY = "Curr_User";
        public const string SAVE_UID = "Net_Core_UID";
        public const string SAVE_TOKEN = "Net_Core_TOKEN";
        private string MarkKey = "Login_Mark_2020";

        /// <summary>
        /// 私有构造
        /// </summary>
        private OperatorProvider()
        {
            //单例模式
        }
        private void Init()
        {
            //初始化
            this._Adapter = new SSOAdapter(GetData);
        }
        private UserInfo GetData(string Uid)
        {
            if (Uid.IsEmpty())
                return null;

            var ui = _OperatorGetData.GetUserInfo(Uid, out string error);
            if (!error.IsEmpty())
                return null;
            else
                return ui;
        }

        /// <summary>
        /// 获取实例，当前提供者
        /// </summary>
        public static OperatorProvider Provider
        {
            get
            {
                if (_Provider == null)
                {
                    lock (@lock)
                    {
                        if (_Provider == null)
                        {
                            _Provider = new OperatorProvider();
                            _Provider._OperatorGetData = IocContainer.Resolve<IOperatorGetData>();
                            _Provider._Operator = IocContainer.Resolve<IOperator>();
                            _Provider.Init();
                        }
                    }
                }
                return _Provider;
            }
        }

        /// <summary>
        /// 验证登录
        /// </summary>
        public Validation<UserInfo> CheckLogin(string account, string password, bool jwt = false)
        {
            string error = "";
            var ui = _OperatorGetData.CheckLogin(account, password, out error);
            if (ui != null)
            {
                ui = this._Adapter.ActivateUser(ui.UserId);
                ui = this._OperatorGetData.UserInfoWith(ui);
                AddCurrent(ui, jwt);
            }

            if (ui == null)
                return FP.Invalid(error);
            else
                return FP.Valid(ui);
        }

        /// <summary>
        /// 填充用户信息
        /// </summary>
        public void AddCurrent(UserInfo UInfo, bool jwt = false)
        {
            if (UInfo.IsNull() || UInfo.UserId.IsEmpty())
                return;

            if (jwt)
                SceneUserCache.SetCache(UInfo);
            else
            {
                SceneUserCache.SetCache(UInfo);
                this._Operator.SetSession(CURRENT_KEY, UInfo.UserId);
                this._Operator.SetSession(UInfo.UserId, UInfo.ToJson());
            }
        }

        public UserInfo Current()
        {
            UserInfo Info = this.GetJWTCurrUser();
            if (Info != null)
                return Info;
            else
                return this.GetMVCCurrUser();
        }
        private UserInfo GetJWTCurrUser()
        {
            var uid = JwtHelper.GetUserID();
            if (uid.IsEmpty())
                return null;
            else
            {
                UserInfo ui = SceneUserCache.GetCache(uid);
                if (ui.IsEmpty())
                    if (SSOLogin())
                        ui = SceneUserCache.GetCache(uid);

                if (ui.IsEmpty())
                    return null;
                else if (this._Adapter.Checking(ui.UserId, ui.Token))
                    return ui;
            }
            return null;
        }
        private bool SSOLogin()
        {
            var Uid = JwtHelper.GetUserID();
            var Token = JwtHelper.GetToken();
            var UInfo = this._Adapter.CheckingUser(Uid, Token);
            if (!UInfo.IsEmpty())
            {
                UInfo = this._OperatorGetData.UserInfoWith(UInfo);
                AddCurrent(UInfo, true);
                return true;
            }
            else
                return false;
        }
        private UserInfo GetMVCCurrUser()
        {
            var SID = this._Operator.GetSession(CURRENT_KEY);
            if (SID.IsEmpty())
                if (CookieLogin())
                    SID = this._Operator.GetSession(CURRENT_KEY);

            if (SID.IsEmpty())
                return null;
            else
            {
                var ui = this._Operator.GetSession(SID)
                   .ToOption()
                   .Map(a => a.ToObject<UserInfo>())
                   .Outcome();

                if (this._Adapter.Checking(ui.UserId, ui.Token))
                    return ui;
            }
            return null;
        }
        private bool CookieLogin()
        {
            var Uid = this._Operator.GetCookies(SAVE_UID);
            var Token = this._Operator.GetCookies(SAVE_TOKEN);
            var UInfo = this._Adapter.CheckingUser(Uid, Token);
            if (!UInfo.IsEmpty())
            {
                UInfo = this._OperatorGetData.UserInfoWith(UInfo);
                AddCurrent(UInfo);
                return true;
            }
            else
                return false;
        }

        /// <summary>
        /// 取确认信息
        /// </summary>
        public UserInfo CheckUser(string Uid)
        {
            var UInfo = this._Adapter.CheckUser(Uid);
            UInfo = this._OperatorGetData.UserInfoWith(UInfo);
            return UInfo;
        }
        /// <summary>
        /// 清空当前数据
        /// </summary>
        public void EmptyCurrentData()
        {
            var uid = this._Operator.GetSession(CURRENT_KEY);
            if (uid.IsEmpty())
                uid = this._Operator.GetCookies(SAVE_UID);

            if (!uid.IsEmpty())
            {
                SceneUserCache.RemoveCache(uid);
                this._Adapter.LogoutUser(uid);
            }

            this._Operator.DeleteCookies(SAVE_UID);
            this._Operator.DeleteCookies(SAVE_TOKEN);
            this._Operator.SessionClear();
        }

        /// <summary>
        /// 写操作日志
        /// </summary>
        public void WriteOperateLog(LogModel operateLogModel)
        {
            if (operateLogModel == null)
                return;

            if (this._OperatorGetData == null)
                return;

            this._OperatorGetData.WriteLog(operateLogModel);
        }

        #region--Session & Cookies--

        public void SetSession(string key, string value)
        {
            this._Operator.SetSession(key, value);
        }

        public string GetSession(string key)
        {
            return this._Operator.GetSession(key);
        }

        public void SessionClear()
        {
            this._Operator.SessionClear();
        }


        public void SetCookies(string key, string value, int minutes = 480)
        {
            this._Operator.SetCookies(key, value, minutes);
        }

        public string GetCookies(string key)
        {
            return this._Operator.GetCookies(key);
        }

        public void DeleteCookies(string key)
        {
            this._Operator.DeleteCookies(key);
        }

        #endregion

        public string GetIP()
        {
            string ip = JwtHelper.GetHttpContext().Connection.RemoteIpAddress.ToString();
            if (ip == "::1")
                return "127.0.0.1";
            else
                return ip;
        }

        #region--Headers--

        public string GetUserAgent()
        {
            return JwtHelper.GetHttpContext().Request.Headers["User-Agent"];
        }

        public string GetAccept()
        {
            return JwtHelper.GetHttpContext().Request.Headers["Accept"];
        }

        public string GetConnection()
        {
            return JwtHelper.GetHttpContext().Request.Headers["connection"];
        }

        #endregion

        /// <summary>
        /// 获取浏览器设配号(为浏览器打一个标记)
        /// </summary>
        private string GetMark()
        {
            string cookieMark = this.GetSession(this.MarkKey);
            if (string.IsNullOrEmpty(cookieMark))
            {
                cookieMark = Guid.NewGuid().ToString("N");
                this.SetSession(this.MarkKey, cookieMark);
            }
            //设备标记
            return cookieMark;
        }
        /// <summary>
        /// 获取当前登录错误次数
        /// </summary>
        public int GetCurrentErrorNum()
        {
            int res = 0;
            string loginMark = this.GetMark();
            string num = SceneUserCache.GetData(loginMark);
            if (!string.IsNullOrEmpty(num))
                res = Convert.ToInt32(num);

            return res;
        }
        /// <summary>
        /// 增加错误次数
        /// </summary>
        public int AddCurrentErrorNum()
        {
            int res = 0;
            string loginMark = this.GetMark();
            string num = this.GetSession(loginMark);
            if (!string.IsNullOrEmpty(num))
                res = Convert.ToInt32(num);

            res++;
            num = res + "";
            SceneUserCache.TryAdd(loginMark, num);
            return res;
        }
        /// <summary>
        /// 清除当前登录错误次数
        /// </summary>
        public void ClearCurrentErrorNum()
        {
            string loginMark = this.GetMark();
            SceneUserCache.TryRemove(loginMark);
        }
    }
}
